package neo.aoi;

import java.math.BigDecimal;

/**
 * This class contains static methods for performing rounding operations. The
 * <code>ROUND_PLACES</code> constant is defined and it indicates the number
 * of places after the decimal point to which numbers will be rounded. A
 * negative value to for this constant will produce roundings above the decimal
 * point, i.e. -1 for 10's, -2 for 100's etc.
 * 
 * @author Carlos Martinez
 */
public class RoundUtils {
	/**
	 * The number of places after the decimal point to round. Default value is
	 * 6.
	 */
	protected int ROUND_PLACES = 6;

	/**
	 * Rounds a given number. The number is rounded to the number of decimal
	 * places defined by <code>ROUND_PLACES</code>
	 * 
	 * @param num
	 *            The number to be rounded
	 * @return The rounded number
	 */
	public double round(double num) {
		return round(num, ROUND_PLACES);
	}

	/**
	 * Rounds a given number. The number is rounded to the number of decimal
	 * places.
	 * 
	 * @param num
	 *            The number to be rounded
	 * @param places
	 * 			  The numer of places to be used
	 * @return The rounded number
	 */
	public static double round(double num, int places) {
		BigDecimal dec = new BigDecimal(num);
		dec = dec.setScale(places, BigDecimal.ROUND_HALF_DOWN);
		return dec.doubleValue();
	}

	/**
	 * Sets the number of rounding places to match the given number. The number
	 * of rounding places is selected in order to fit the most significant
	 * figure.
	 * 
	 * <table>
	 * <tr>
	 * <th>Res</th>
	 * <th>Places</th>
	 * </tr>
	 * <tr>
	 * <td>10.0</td>
	 * <td>-1</td>
	 * </tr>
	 * <tr>
	 * <td>1.0</td>
	 * <td>0</td>
	 * </tr>
	 * <tr>
	 * <td>0.1</td>
	 * <td>1</td>
	 * </tr>
	 * <tr>
	 * <td>0.01</td>
	 * <td>2</td>
	 * </tr>
	 * <tr>
	 * <td>0.03</td>
	 * <td>2</td>
	 * </tr>
	 * </table>
	 * 
	 * @param res
	 *            The desired resoultion
	 */
	public void matchRoundingPlaces(double res) {
		ROUND_PLACES = getRoundingPlaces(res);
	}

	/**
	 * Finds the number of rounding places to match the given number. The number
	 * of rounding places is selected in order to fit the most significant
	 * figure.
	 * 
	 * <table>
	 * <tr>
	 * <th>Res</th>
	 * <th>Places</th>
	 * </tr>
	 * <tr>
	 * <td>10.0</td>
	 * <td>-1</td>
	 * </tr>
	 * <tr>
	 * <td>1.0</td>
	 * <td>0</td>
	 * </tr>
	 * <tr>
	 * <td>0.1</td>
	 * <td>1</td>
	 * </tr>
	 * <tr>
	 * <td>0.01</td>
	 * <td>2</td>
	 * </tr>
	 * <tr>
	 * <td>0.03</td>
	 * <td>2</td>
	 * </tr>
	 * </table>
	 * 
	 * @param res
	 *            The desired resoultion
	 */
	public static int getRoundingPlaces(double res) {
		double places = Math.ceil(Math.abs(Math.log10(res)));
		return (int) places;
	}
	
	/**
	 * Set the value of the <code>ROUND_PLACES</code> constant.
	 * 
	 * @param places
	 *            The new value for the <code>ROUND_PLACES</code> constant.
	 */
	public void setRoundingPlaces(int places) {
		ROUND_PLACES = places;
	}

	/**
	 * Returns the current value of <code>ROUND_PLACES</code> constant.
	 * 
	 * @return the value of <code>ROUND_PLACES</code> constant.
	 */
	public int getRoundingPlaces() {
		return ROUND_PLACES;
	}
}